#include <iostream>
#include <json/value.h>
#include <json/writer.h>
#include <utility>
#include <stdexcept>
#include <cstring>
#include <cassert>
#ifdef JSON_USE_CPPTL
# include <cpptl/conststring.h>
#endif
#include <cstddef>    // size_t
#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
# include "json_batchallocator.h"
#endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR

#define JSON_ASSERT_UNREACHABLE assert( false )
#define JSON_ASSERT( condition ) assert( condition );  // @todo <= change this into an exception throw
#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message );

namespace Json {

	const Value Value::null;
	const Int Value::minInt = Int( ~(UInt(-1)/2) );
	const Int Value::maxInt = Int( UInt(-1)/2 );
	const UInt Value::maxUInt = UInt(-1);

	// A "safe" implementation of strdup. Allow null pointer to be passed. 
	// Also avoid warning on msvc80.
	//
	//inline char *safeStringDup( const char *czstring )
	//{
	//   if ( czstring )
	//   {
	//      const size_t length = (unsigned int)( strlen(czstring) + 1 );
	//      char *newString = static_cast<char *>( malloc( length ) );
	//      memcpy( newString, czstring, length );
	//      return newString;
	//   }
	//   return 0;
	//}
	//
	//inline char *safeStringDup( const std::string &str )
	//{
	//   if ( !str.empty() )
	//   {
	//      const size_t length = str.length();
	//      char *newString = static_cast<char *>( malloc( length + 1 ) );
	//      memcpy( newString, str.c_str(), length );
	//      newString[length] = 0;
	//      return newString;
	//   }
	//   return 0;
	//}

	ValueAllocator::~ValueAllocator()
	{
	}

	class DefaultValueAllocator : public ValueAllocator
	{
	public:
		virtual ~DefaultValueAllocator()
		{
		}

		virtual char *makeMemberName( const char *memberName )
		{
			return duplicateStringValue( memberName );
		}

		virtual void releaseMemberName( char *memberName )
		{
			releaseStringValue( memberName );
		}

		virtual char *duplicateStringValue( const char *value, 
			unsigned int length = unknown )
		{
			//@todo invesgate this old optimization
			//if ( !value  ||  value[0] == 0 )
			//   return 0;

			if ( length == unknown )
				length = (unsigned int)strlen(value);
			char *newString = static_cast<char *>( malloc( length + 1 ) );
			memcpy( newString, value, length );
			newString[length] = 0;
			return newString;
		}

		virtual void releaseStringValue( char *value )
		{
			if ( value )
				free( value );
		}
	};

	static ValueAllocator *&valueAllocator()
	{
		static DefaultValueAllocator defaultAllocator;
		static ValueAllocator *valueAllocator = &defaultAllocator;
		return valueAllocator;
	}

	static struct DummyValueAllocatorInitializer {
		DummyValueAllocatorInitializer() 
		{
			valueAllocator();      // ensure valueAllocator() statics are initialized before main().
		}
	} dummyValueAllocatorInitializer;



	// //////////////////////////////////////////////////////////////////
	// //////////////////////////////////////////////////////////////////
	// //////////////////////////////////////////////////////////////////
	// ValueInternals...
	// //////////////////////////////////////////////////////////////////
	// //////////////////////////////////////////////////////////////////
	// //////////////////////////////////////////////////////////////////
#ifdef JSON_VALUE_USE_INTERNAL_MAP
# include "json_internalarray.inl"
# include "json_internalmap.inl"
#endif // JSON_VALUE_USE_INTERNAL_MAP

# include "json_valueiterator.inl"


	// //////////////////////////////////////////////////////////////////
	// //////////////////////////////////////////////////////////////////
	// //////////////////////////////////////////////////////////////////
	// class Value::CommentInfo
	// //////////////////////////////////////////////////////////////////
	// //////////////////////////////////////////////////////////////////
	// //////////////////////////////////////////////////////////////////


	Value::CommentInfo::CommentInfo()
		: comment_( 0 )
	{
	}

	Value::CommentInfo::~CommentInfo()
	{
		if ( comment_ )
			valueAllocator()->releaseStringValue( comment_ );
	}


	void 
		Value::CommentInfo::setComment( const char *text )
	{
		if ( comment_ )
			valueAllocator()->releaseStringValue( comment_ );
		JSON_ASSERT( text );
		JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
		// It seems that /**/ style comments are acceptable as well.
		comment_ = valueAllocator()->duplicateStringValue( text );
	}


	// //////////////////////////////////////////////////////////////////
	// //////////////////////////////////////////////////////////////////
	// //////////////////////////////////////////////////////////////////
	// class Value::CZString
	// //////////////////////////////////////////////////////////////////
	// //////////////////////////////////////////////////////////////////
	// //////////////////////////////////////////////////////////////////
# ifndef JSON_VALUE_USE_INTERNAL_MAP

	// Notes: index_ indicates if the string was allocated when
	// a string is stored.

	Value::CZString::CZString( int index )
		: cstr_( 0 )
		, index_( index )
	{
	}

	Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
		: cstr_( allocate == duplicate ? valueAllocator()->makeMemberName(cstr) 
		: cstr )
		, index_( allocate )
	{
	}

	Value::CZString::CZString( const CZString &other )
		: cstr_( other.index_ != noDuplication &&  other.cstr_ != 0
		?  valueAllocator()->makeMemberName( other.cstr_ )
		: other.cstr_ )
		, index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
		: other.index_ )
	{
	}

	Value::CZString::~CZString()
	{
		if ( cstr_  &&  index_ == duplicate )
			valueAllocator()->releaseMemberName( const_cast<char *>( cstr_ ) );
	}

	void 
		Value::CZString::swap( CZString &other )
	{
		std::swap( cstr_, other.cstr_ );
		std::swap( index_, other.index_ );
	}

	Value::CZString &
		Value::CZString::operator =( const CZString &other )
	{
		CZString temp( other );
		swap( temp );
		return *this;
	}

	bool 
		Value::CZString::operator<( const CZString &other ) const 
	{
		if ( cstr_ )
			return strcmp( cstr_, other.cstr_ ) < 0;
		return index_ < other.index_;
	}

	bool 
		Value::CZString::operator==( const CZString &other ) const 
	{
		if ( cstr_ )
			return strcmp( cstr_, other.cstr_ ) == 0;
		return index_ == other.index_;
	}


	int 
		Value::CZString::index() const
	{
		return index_;
	}


	const char *
		Value::CZString::c_str() const
	{
		return cstr_;
	}

	bool 
		Value::CZString::isStaticString() const
	{
		return index_ == noDuplication;
	}

#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP


	// //////////////////////////////////////////////////////////////////
	// //////////////////////////////////////////////////////////////////
	// //////////////////////////////////////////////////////////////////
	// class Value::Value
	// //////////////////////////////////////////////////////////////////
	// //////////////////////////////////////////////////////////////////
	// //////////////////////////////////////////////////////////////////

	/*! \internal Default constructor initialization must be equivalent to:
	* memset( this, 0, sizeof(Value) )
	* This optimization is used in ValueInternalMap fast allocator.
	*/
	Value::Value( ValueType type )
		: type_( type )
		, allocated_( 0 )
		, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
		, itemIsUsed_( 0 )
#endif
	{
		switch ( type )
		{
		case nullValue:
			break;
		case intValue:
		case uintValue:
			value_.int_ = 0;
			break;
		case realValue:
			value_.real_ = 0.0;
			break;
		case stringValue:
			value_.string_ = 0;
			break;
#ifndef JSON_VALUE_USE_INTERNAL_MAP
		case arrayValue:
		case objectValue:
			value_.map_ = new ObjectValues();
			break;
#else
		case arrayValue:
			value_.array_ = arrayAllocator()->newArray();
			break;
		case objectValue:
			value_.map_ = mapAllocator()->newMap();
			break;
#endif
		case booleanValue:
			value_.bool_ = false;
			break;
		default:
			JSON_ASSERT_UNREACHABLE;
		}
	}


	Value::Value( Int value )
		: type_( intValue )
		, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
		, itemIsUsed_( 0 )
#endif
	{
		value_.int_ = value;
	}


	Value::Value( UInt value )
		: type_( uintValue )
		, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
		, itemIsUsed_( 0 )
#endif
	{
		value_.uint_ = value;
	}

	Value::Value( double value )
		: type_( realValue )
		, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
		, itemIsUsed_( 0 )
#endif
	{
		value_.real_ = value;
	}

	Value::Value( const char *value )
		: type_( stringValue )
		, allocated_( true )
		, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
		, itemIsUsed_( 0 )
#endif
	{
		value_.string_ = valueAllocator()->duplicateStringValue( value );
	}


	Value::Value( const char *beginValue, 
		const char *endValue )
		: type_( stringValue )
		, allocated_( true )
		, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
		, itemIsUsed_( 0 )
#endif
	{
		value_.string_ = valueAllocator()->duplicateStringValue( beginValue, 
			UInt(endValue - beginValue) );
	}


	Value::Value( const std::string &value )
		: type_( stringValue )
		, allocated_( true )
		, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
		, itemIsUsed_( 0 )
#endif
	{
		value_.string_ = valueAllocator()->duplicateStringValue( value.c_str(), 
			(unsigned int)value.length() );

	}

	Value::Value( const StaticString &value )
		: type_( stringValue )
		, allocated_( false )
		, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
		, itemIsUsed_( 0 )
#endif
	{
		value_.string_ = const_cast<char *>( value.c_str() );
	}


# ifdef JSON_USE_CPPTL
	Value::Value( const CppTL::ConstString &value )
		: type_( stringValue )
		, allocated_( true )
		, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
		, itemIsUsed_( 0 )
#endif
	{
		value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() );
	}
# endif

	Value::Value( bool value )
		: type_( booleanValue )
		, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
		, itemIsUsed_( 0 )
#endif
	{
		value_.bool_ = value;
	}


	Value::Value( const Value &other )
		: type_( other.type_ )
		, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
		, itemIsUsed_( 0 )
#endif
	{
		switch ( type_ )
		{
		case nullValue:
		case intValue:
		case uintValue:
		case realValue:
		case booleanValue:
			value_ = other.value_;
			break;
		case stringValue:
			if ( other.value_.string_ )
			{
				value_.string_ = valueAllocator()->duplicateStringValue( other.value_.string_ );
				allocated_ = true;
			}
			else
				value_.string_ = 0;
			break;
#ifndef JSON_VALUE_USE_INTERNAL_MAP
		case arrayValue:
		case objectValue:
			value_.map_ = new ObjectValues( *other.value_.map_ );
			break;
#else
		case arrayValue:
			value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
			break;
		case objectValue:
			value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
			break;
#endif
		default:
			JSON_ASSERT_UNREACHABLE;
		}
		if ( other.comments_ )
		{
			comments_ = new CommentInfo[numberOfCommentPlacement];
			for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
			{
				const CommentInfo &otherComment = other.comments_[comment];
				if ( otherComment.comment_ )
					comments_[comment].setComment( otherComment.comment_ );
			}
		}
	}


	Value::~Value()
	{
		switch ( type_ )
		{
		case nullValue:
		case intValue:
		case uintValue:
		case realValue:
		case booleanValue:
			break;
		case stringValue:
			if ( allocated_ )
				valueAllocator()->releaseStringValue( value_.string_ );
			break;
#ifndef JSON_VALUE_USE_INTERNAL_MAP
		case arrayValue:
		case objectValue:
			delete value_.map_;
			break;
#else
		case arrayValue:
			arrayAllocator()->destructArray( value_.array_ );
			break;
		case objectValue:
			mapAllocator()->destructMap( value_.map_ );
			break;
#endif
		default:
			JSON_ASSERT_UNREACHABLE;
		}

		if ( comments_ )
			delete[] comments_;

	}

	Value &
		Value::operator=( const Value &other )
	{
		Value temp( other );
		swap( temp );
		return *this;
	}

	void 
		Value::swap( Value &other )
	{
		ValueType temp = type_;
		type_ = other.type_;
		other.type_ = temp;
		std::swap( value_, other.value_ );
		int temp2 = allocated_;
		allocated_ = other.allocated_;
		other.allocated_ = temp2;
	}

	Value & Value::operator=( const ValueType &other )
	{
		Value temp( other );
		swap( temp );
		return *this;
	}
	Value & Value::operator=( const Int &other )
	{
		Value temp( other );
		swap( temp );
		return *this;
	}
	Value & Value::operator=( const UInt &other )
	{
		Value temp( other );
		swap( temp );
		return *this;
	}
	Value & Value::operator=( const double &other )
	{
		Value temp( other );
		swap( temp );
		return *this;
	}
	Value & Value::operator=( const char * &other )
	{
		Value temp( other );
		swap( temp );
		return *this;
	}
	Value & Value::operator=( const StaticString &other )
	{
		Value temp( other );
		swap( temp );
		return *this;
	}
	Value & Value::operator=( const bool&other )
	{
		Value temp( other );
		swap( temp );
		return *this;
	}
	ValueType 
		Value::type() const
	{
		return type_;
	}


	int 
		Value::compare( const Value &other )
	{
		/*
		int typeDelta = other.type_ - type_;
		switch ( type_ )
		{
		case nullValue:

		return other.type_ == type_;
		case intValue:
		if ( other.type_.isNumeric()
		case uintValue:
		case realValue:
		case booleanValue:
		break;
		case stringValue,
		break;
		case arrayValue:
		delete value_.array_;
		break;
		case objectValue:
		delete value_.map_;
		default:
		JSON_ASSERT_UNREACHABLE;
		}
		*/
		return 0;  // unreachable
	}

	bool 
		Value::operator <( const Value &other ) const
	{
		int typeDelta = type_ - other.type_;
		if ( typeDelta )
			return typeDelta < 0 ? true : false;
		switch ( type_ )
		{
		case nullValue:
			return false;
		case intValue:
			return value_.int_ < other.value_.int_;
		case uintValue:
			return value_.uint_ < other.value_.uint_;
		case realValue:
			return value_.real_ < other.value_.real_;
		case booleanValue:
			return value_.bool_ < other.value_.bool_;
		case stringValue:
			return ( value_.string_ == 0  &&  other.value_.string_ )
				|| ( other.value_.string_  
				&&  value_.string_  
				&& strcmp( value_.string_, other.value_.string_ ) < 0 );
#ifndef JSON_VALUE_USE_INTERNAL_MAP
		case arrayValue:
		case objectValue:
			{
				int delta = int( value_.map_->size() - other.value_.map_->size() );
				if ( delta )
					return delta < 0;
				return (*value_.map_) < (*other.value_.map_);
			}
#else
		case arrayValue:
			return value_.array_->compare( *(other.value_.array_) ) < 0;
		case objectValue:
			return value_.map_->compare( *(other.value_.map_) ) < 0;
#endif
		default:
			JSON_ASSERT_UNREACHABLE;
		}
		return 0;  // unreachable
	}

	bool 
		Value::operator <=( const Value &other ) const
	{
		return !(other > *this);
	}

	bool 
		Value::operator >=( const Value &other ) const
	{
		return !(*this < other);
	}

	bool 
		Value::operator >( const Value &other ) const
	{
		return other < *this;
	}

	bool 
		Value::operator ==( const Value &other ) const
	{
		//if ( type_ != other.type_ )
		// GCC 2.95.3 says:
		// attempt to take address of bit-field structure member `Json::Value::type_'
		// Beats me, but a temp solves the problem.
		int temp = other.type_;
		if ( type_ != temp )
			return false;
		switch ( type_ )
		{
		case nullValue:
			return true;
		case intValue:
			return value_.int_ == other.value_.int_;
		case uintValue:
			return value_.uint_ == other.value_.uint_;
		case realValue:
			return value_.real_ == other.value_.real_;
		case booleanValue:
			return value_.bool_ == other.value_.bool_;
		case stringValue:
			return ( value_.string_ == other.value_.string_ )
				|| ( other.value_.string_  
				&&  value_.string_  
				&& strcmp( value_.string_, other.value_.string_ ) == 0 );
#ifndef JSON_VALUE_USE_INTERNAL_MAP
		case arrayValue:
		case objectValue:
			return value_.map_->size() == other.value_.map_->size()
				&& (*value_.map_) == (*other.value_.map_);
#else
		case arrayValue:
			return value_.array_->compare( *(other.value_.array_) ) == 0;
		case objectValue:
			return value_.map_->compare( *(other.value_.map_) ) == 0;
#endif
		default:
			JSON_ASSERT_UNREACHABLE;
		}
		return 0;  // unreachable
	}

	bool 
		Value::operator !=( const Value &other ) const
	{
		return !( *this == other );
	}

	const char *
		Value::asCString() const
	{
		JSON_ASSERT( type_ == stringValue );
		return value_.string_;
	}


	std::string 
		Value::asString() const
	{
		switch ( type_ )
		{
		case nullValue:
			return "";
		case stringValue:
			return value_.string_ ? value_.string_ : "";
		case booleanValue:
			return value_.bool_ ? "true" : "false";
		case intValue:
		case uintValue:
		case realValue:
		case arrayValue:
		case objectValue:
			JSON_ASSERT_MESSAGE( false, "Type is not convertible to string" );
		default:
			JSON_ASSERT_UNREACHABLE;
		}
		return ""; // unreachable
	}

# ifdef JSON_USE_CPPTL
	CppTL::ConstString 
		Value::asConstString() const
	{
		return CppTL::ConstString( asString().c_str() );
	}
# endif

	Value::Int 
		Value::asInt() const
	{
		switch ( type_ )
		{
		case nullValue:
			return 0;
		case intValue:
			return value_.int_;
		case uintValue:
			JSON_ASSERT_MESSAGE( value_.uint_ < (unsigned)maxInt, "integer out of signed integer range" );
			return value_.uint_;
		case realValue:
			JSON_ASSERT_MESSAGE( value_.real_ >= minInt  &&  value_.real_ <= maxInt, "Real out of signed integer range" );
			return Int( value_.real_ );
		case booleanValue:
			return value_.bool_ ? 1 : 0;
		case stringValue:
		case arrayValue:
		case objectValue:
			JSON_ASSERT_MESSAGE( false, "Type is not convertible to int" );
		default:
			JSON_ASSERT_UNREACHABLE;
		}
		return 0; // unreachable;
	}

	Value::UInt 
		Value::asUInt() const
	{
		switch ( type_ )
		{
		case nullValue:
			return 0;
		case intValue:
			JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
			return value_.int_;
		case uintValue:
			return value_.uint_;
		case realValue:
			JSON_ASSERT_MESSAGE( value_.real_ >= 0  &&  value_.real_ <= maxUInt,  "Real out of unsigned integer range" );
			return UInt( value_.real_ );
		case booleanValue:
			return value_.bool_ ? 1 : 0;
		case stringValue:
		case arrayValue:
		case objectValue:
			JSON_ASSERT_MESSAGE( false, "Type is not convertible to uint" );
		default:
			JSON_ASSERT_UNREACHABLE;
		}
		return 0; // unreachable;
	}

	double 
		Value::asDouble() const
	{
		switch ( type_ )
		{
		case nullValue:
			return 0.0;
		case intValue:
			return value_.int_;
		case uintValue:
			return value_.uint_;
		case realValue:
			return value_.real_;
		case booleanValue:
			return value_.bool_ ? 1.0 : 0.0;
		case stringValue:
		case arrayValue:
		case objectValue:
			JSON_ASSERT_MESSAGE( false, "Type is not convertible to double" );
		default:
			JSON_ASSERT_UNREACHABLE;
		}
		return 0; // unreachable;
	}

	bool 
		Value::asBool() const
	{
		switch ( type_ )
		{
		case nullValue:
			return false;
		case intValue:
		case uintValue:
			return value_.int_ != 0;
		case realValue:
			return value_.real_ != 0.0;
		case booleanValue:
			return value_.bool_;
		case stringValue:
			return value_.string_  &&  value_.string_[0] != 0;
		case arrayValue:
		case objectValue:
			return value_.map_->size() != 0;
		default:
			JSON_ASSERT_UNREACHABLE;
		}
		return false; // unreachable;
	}


	bool 
		Value::isConvertibleTo( ValueType other ) const
	{
		switch ( type_ )
		{
		case nullValue:
			return true;
		case intValue:
			return ( other == nullValue  &&  value_.int_ == 0 )
				|| other == intValue
				|| ( other == uintValue  && value_.int_ >= 0 )
				|| other == realValue
				|| other == stringValue
				|| other == booleanValue;
		case uintValue:
			return ( other == nullValue  &&  value_.uint_ == 0 )
				|| ( other == intValue  && value_.uint_ <= (unsigned)maxInt )
				|| other == uintValue
				|| other == realValue
				|| other == stringValue
				|| other == booleanValue;
		case realValue:
			return ( other == nullValue  &&  value_.real_ == 0.0 )
				|| ( other == intValue  &&  value_.real_ >= minInt  &&  value_.real_ <= maxInt )
				|| ( other == uintValue  &&  value_.real_ >= 0  &&  value_.real_ <= maxUInt )
				|| other == realValue
				|| other == stringValue
				|| other == booleanValue;
		case booleanValue:
			return ( other == nullValue  &&  value_.bool_ == false )
				|| other == intValue
				|| other == uintValue
				|| other == realValue
				|| other == stringValue
				|| other == booleanValue;
		case stringValue:
			return other == stringValue
				|| ( other == nullValue  &&  (!value_.string_  ||  value_.string_[0] == 0) );
		case arrayValue:
			return other == arrayValue
				||  ( other == nullValue  &&  value_.map_->size() == 0 );
		case objectValue:
			return other == objectValue
				||  ( other == nullValue  &&  value_.map_->size() == 0 );
		default:
			JSON_ASSERT_UNREACHABLE;
		}
		return false; // unreachable;
	}


	/// Number of values in array or object
	Value::UInt 
		Value::size() const
	{
		switch ( type_ )
		{
		case nullValue:
		case intValue:
		case uintValue:
		case realValue:
		case booleanValue:
		case stringValue:
			return 0;
#ifndef JSON_VALUE_USE_INTERNAL_MAP
		case arrayValue:  // size of the array is highest index + 1
			if ( !value_.map_->empty() )
			{
				ObjectValues::const_iterator itLast = value_.map_->end();
				--itLast;
				return (*itLast).first.index()+1;
			}
			return 0;
		case objectValue:
			return Int( value_.map_->size() );
#else
		case arrayValue:
			return Int( value_.array_->size() );
		case objectValue:
			return Int( value_.map_->size() );
#endif
		default:
			JSON_ASSERT_UNREACHABLE;
		}
		return 0; // unreachable;
	}


	bool 
		Value::empty() const
	{
		if ( isNull() || isArray() || isObject() )
			return size() == 0u;
		else
			return false;
	}


	bool
		Value::operator!() const
	{
		return isNull();
	}


	void 
		Value::clear()
	{
		JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue  || type_ == objectValue );

		switch ( type_ )
		{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
	case arrayValue:
	case objectValue:
		value_.map_->clear();
		break;
#else
	case arrayValue:
		value_.array_->clear();
		break;
	case objectValue:
		value_.map_->clear();
		break;
#endif
	default:
		break;
		}
	}

	void 
		Value::resize( UInt newSize )
	{
		JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
		if ( type_ == nullValue )
			*this = Value( arrayValue );
#ifndef JSON_VALUE_USE_INTERNAL_MAP
		UInt oldSize = size();
		if ( newSize == 0 )
			clear();
		else if ( newSize > oldSize )
			(*this)[ newSize - 1 ];
		else
		{
			for ( UInt index = newSize; index < oldSize; ++index )
				value_.map_->erase( index );
			assert( size() == newSize );
		}
#else
		value_.array_->resize( newSize );
#endif
	}


	Value &
		Value::operator[]( UInt index )
	{
		JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
		if ( type_ == nullValue )
			*this = Value( arrayValue );
#ifndef JSON_VALUE_USE_INTERNAL_MAP
		CZString key( index );
		ObjectValues::iterator it = value_.map_->lower_bound( key );
		if ( it != value_.map_->end()  &&  (*it).first == key )
			return (*it).second;

		ObjectValues::value_type defaultValue( key, null );
		it = value_.map_->insert( it, defaultValue );
		return (*it).second;
#else
		return value_.array_->resolveReference( index );
#endif
	}


	const Value &
		Value::operator[]( UInt index ) const
	{
		JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
		if ( type_ == nullValue )
			return null;
#ifndef JSON_VALUE_USE_INTERNAL_MAP
		CZString key( index );
		ObjectValues::const_iterator it = value_.map_->find( key );
		if ( it == value_.map_->end() )
			return null;
		return (*it).second;
#else
		Value *value = value_.array_->find( index );
		return value ? *value : null;
#endif
	}


	Value &
		Value::operator[]( const char *key )
	{
		return resolveReference( key, false );
	}


	Value &
		Value::resolveReference( const char *key, 
		bool isStatic )
	{
		JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
		if ( type_ == nullValue )
			*this = Value( objectValue );
#ifndef JSON_VALUE_USE_INTERNAL_MAP
		CZString actualKey( key, isStatic ? CZString::noDuplication 
			: CZString::duplicateOnCopy );
		ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
		if ( it != value_.map_->end()  &&  (*it).first == actualKey )
			return (*it).second;

		ObjectValues::value_type defaultValue( actualKey, null );
		it = value_.map_->insert( it, defaultValue );
		Value &value = (*it).second;
		return value;
#else
		return value_.map_->resolveReference( key, isStatic );
#endif
	}


	Value 
		Value::get( UInt index, 
		const Value &defaultValue ) const
	{
		const Value *value = &((*this)[index]);
		return value == &null ? defaultValue : *value;
	}


	bool 
		Value::isValidIndex( UInt index ) const
	{
		return index < size();
	}



	const Value &
		Value::operator[]( const char *key ) const
	{
		JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
		if ( type_ == nullValue )
			return null;
#ifndef JSON_VALUE_USE_INTERNAL_MAP
		CZString actualKey( key, CZString::noDuplication );
		ObjectValues::const_iterator it = value_.map_->find( actualKey );
		if ( it == value_.map_->end() )
			return null;
		return (*it).second;
#else
		const Value *value = value_.map_->find( key );
		return value ? *value : null;
#endif
	}


	Value &
		Value::operator[]( const std::string &key )
	{
		return (*this)[ key.c_str() ];
	}


	const Value &
		Value::operator[]( const std::string &key ) const
	{
		return (*this)[ key.c_str() ];
	}

	Value &
		Value::operator[]( const StaticString &key )
	{
		return resolveReference( key, true );
	}


# ifdef JSON_USE_CPPTL
	Value &
		Value::operator[]( const CppTL::ConstString &key )
	{
		return (*this)[ key.c_str() ];
	}


	const Value &
		Value::operator[]( const CppTL::ConstString &key ) const
	{
		return (*this)[ key.c_str() ];
	}
# endif


	Value &
		Value::append( const Value &value )
	{
		return (*this)[size()] = value;
	}


	Value 
		Value::get( const char *key, 
		const Value &defaultValue ) const
	{
		const Value *value = &((*this)[key]);
		return value == &null ? defaultValue : *value;
	}


	Value 
		Value::get( const std::string &key,
		const Value &defaultValue ) const
	{
		return get( key.c_str(), defaultValue );
	}

	Value
		Value::removeMember( const char* key )
	{
		JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
		if ( type_ == nullValue )
			return null;
#ifndef JSON_VALUE_USE_INTERNAL_MAP
		CZString actualKey( key, CZString::noDuplication );
		ObjectValues::iterator it = value_.map_->find( actualKey );
		if ( it == value_.map_->end() )
			return null;
		Value old(it->second);
		value_.map_->erase(it);
		return old;
#else
		Value *value = value_.map_->find( key );
		if (value){
			Value old(*value);
			value_.map_.remove( key );
			return old;
		} else {
			return null;
		}
#endif
	}

	Value
		Value::removeMember( const std::string &key )
	{
		return removeMember( key.c_str() );
	}

# ifdef JSON_USE_CPPTL
	Value 
		Value::get( const CppTL::ConstString &key,
		const Value &defaultValue ) const
	{
		return get( key.c_str(), defaultValue );
	}
# endif

	bool 
		Value::isMember( const char *key ) const
	{
		const Value *value = &((*this)[key]);
		return value != &null;
	}


	bool 
		Value::isMember( const std::string &key ) const
	{
		return isMember( key.c_str() );
	}


# ifdef JSON_USE_CPPTL
	bool 
		Value::isMember( const CppTL::ConstString &key ) const
	{
		return isMember( key.c_str() );
	}
#endif

	Value::Members 
		Value::getMemberNames() const
	{
		JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
		if ( type_ == nullValue )
			return Value::Members();
		Members members;
		members.reserve( value_.map_->size() );
#ifndef JSON_VALUE_USE_INTERNAL_MAP
		ObjectValues::const_iterator it = value_.map_->begin();
		ObjectValues::const_iterator itEnd = value_.map_->end();
		for ( ; it != itEnd; ++it )
			members.push_back( std::string( (*it).first.c_str() ) );
#else
		ValueInternalMap::IteratorState it;
		ValueInternalMap::IteratorState itEnd;
		value_.map_->makeBeginIterator( it );
		value_.map_->makeEndIterator( itEnd );
		for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
			members.push_back( std::string( ValueInternalMap::key( it ) ) );
#endif
		return members;
	}
	//
	//# ifdef JSON_USE_CPPTL
	//EnumMemberNames
	//Value::enumMemberNames() const
	//{
	//   if ( type_ == objectValue )
	//   {
	//      return CppTL::Enum::any(  CppTL::Enum::transform(
	//         CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
	//         MemberNamesTransform() ) );
	//   }
	//   return EnumMemberNames();
	//}
	//
	//
	//EnumValues 
	//Value::enumValues() const
	//{
	//   if ( type_ == objectValue  ||  type_ == arrayValue )
	//      return CppTL::Enum::anyValues( *(value_.map_), 
	//                                     CppTL::Type<const Value &>() );
	//   return EnumValues();
	//}
	//
	//# endif


	bool
		Value::isNull() const
	{
		return type_ == nullValue;
	}


	bool 
		Value::isBool() const
	{
		return type_ == booleanValue;
	}


	bool 
		Value::isInt() const
	{
		return type_ == intValue;
	}


	bool 
		Value::isUInt() const
	{
		return type_ == uintValue;
	}


	bool 
		Value::isIntegral() const
	{
		return type_ == intValue  
			||  type_ == uintValue  
			||  type_ == booleanValue;
	}


	bool 
		Value::isDouble() const
	{
		return type_ == realValue;
	}


	bool 
		Value::isNumeric() const
	{
		return isIntegral() || isDouble();
	}


	bool 
		Value::isString() const
	{
		return type_ == stringValue;
	}


	bool 
		Value::isArray() const
	{
		return type_ == nullValue  ||  type_ == arrayValue;
	}


	bool 
		Value::isObject() const
	{
		return type_ == nullValue  ||  type_ == objectValue;
	}


	void 
		Value::setComment( const char *comment,
		CommentPlacement placement )
	{
		if ( !comments_ )
			comments_ = new CommentInfo[numberOfCommentPlacement];
		comments_[placement].setComment( comment );
	}


	void 
		Value::setComment( const std::string &comment,
		CommentPlacement placement )
	{
		setComment( comment.c_str(), placement );
	}


	bool 
		Value::hasComment( CommentPlacement placement ) const
	{
		return comments_ != 0  &&  comments_[placement].comment_ != 0;
	}

	std::string 
		Value::getComment( CommentPlacement placement ) const
	{
		if ( hasComment(placement) )
			return comments_[placement].comment_;
		return "";
	}


	std::string 
		Value::toStyledString() const
	{
		StyledWriter writer;
		return writer.write( *this );
	}


	Value::const_iterator 
		Value::begin() const
	{
		switch ( type_ )
		{
#ifdef JSON_VALUE_USE_INTERNAL_MAP
	case arrayValue:
		if ( value_.array_ )
		{
			ValueInternalArray::IteratorState it;
			value_.array_->makeBeginIterator( it );
			return const_iterator( it );
		}
		break;
	case objectValue:
		if ( value_.map_ )
		{
			ValueInternalMap::IteratorState it;
			value_.map_->makeBeginIterator( it );
			return const_iterator( it );
		}
		break;
#else
	case arrayValue:
	case objectValue:
		if ( value_.map_ )
			return const_iterator( value_.map_->begin() );
		break;
#endif
	default:
		break;
		}
		return const_iterator();
	}

	Value::const_iterator 
		Value::end() const
	{
		switch ( type_ )
		{
#ifdef JSON_VALUE_USE_INTERNAL_MAP
	case arrayValue:
		if ( value_.array_ )
		{
			ValueInternalArray::IteratorState it;
			value_.array_->makeEndIterator( it );
			return const_iterator( it );
		}
		break;
	case objectValue:
		if ( value_.map_ )
		{
			ValueInternalMap::IteratorState it;
			value_.map_->makeEndIterator( it );
			return const_iterator( it );
		}
		break;
#else
	case arrayValue:
	case objectValue:
		if ( value_.map_ )
			return const_iterator( value_.map_->end() );
		break;
#endif
	default:
		break;
		}
		return const_iterator();
	}


	Value::iterator 
		Value::begin()
	{
		switch ( type_ )
		{
#ifdef JSON_VALUE_USE_INTERNAL_MAP
	case arrayValue:
		if ( value_.array_ )
		{
			ValueInternalArray::IteratorState it;
			value_.array_->makeBeginIterator( it );
			return iterator( it );
		}
		break;
	case objectValue:
		if ( value_.map_ )
		{
			ValueInternalMap::IteratorState it;
			value_.map_->makeBeginIterator( it );
			return iterator( it );
		}
		break;
#else
	case arrayValue:
	case objectValue:
		if ( value_.map_ )
			return iterator( value_.map_->begin() );
		break;
#endif
	default:
		break;
		}
		return iterator();
	}

	Value::iterator 
		Value::end()
	{
		switch ( type_ )
		{
#ifdef JSON_VALUE_USE_INTERNAL_MAP
	case arrayValue:
		if ( value_.array_ )
		{
			ValueInternalArray::IteratorState it;
			value_.array_->makeEndIterator( it );
			return iterator( it );
		}
		break;
	case objectValue:
		if ( value_.map_ )
		{
			ValueInternalMap::IteratorState it;
			value_.map_->makeEndIterator( it );
			return iterator( it );
		}
		break;
#else
	case arrayValue:
	case objectValue:
		if ( value_.map_ )
			return iterator( value_.map_->end() );
		break;
#endif
	default:
		break;
		}
		return iterator();
	}

	 
	// class PathArgument
	// //////////////////////////////////////////////////////////////////

	PathArgument::PathArgument()
		: kind_( kindNone )
	{
	}


	PathArgument::PathArgument( Value::UInt index )
		: index_( index )
		, kind_( kindIndex )
	{
	}


	PathArgument::PathArgument( const char *key )
		: key_( key )
		, kind_( kindKey )
	{
	}


	PathArgument::PathArgument( const std::string &key )
		: key_( key.c_str() )
		, kind_( kindKey )
	{
	}

	// class Path
	// //////////////////////////////////////////////////////////////////

	Path::Path( const std::string &path,
		const PathArgument &a1,
		const PathArgument &a2,
		const PathArgument &a3,
		const PathArgument &a4,
		const PathArgument &a5 )
	{
		InArgs in;
		in.push_back( &a1 );
		in.push_back( &a2 );
		in.push_back( &a3 );
		in.push_back( &a4 );
		in.push_back( &a5 );
		makePath( path, in );
	}


	void 
		Path::makePath( const std::string &path,
		const InArgs &in )
	{
		const char *current = path.c_str();
		const char *end = current + path.length();
		InArgs::const_iterator itInArg = in.begin();
		while ( current != end )
		{
			if ( *current == '[' )
			{
				++current;
				if ( *current == '%' )
					addPathInArg( path, in, itInArg, PathArgument::kindIndex );
				else
				{
					Value::UInt index = 0;
					for ( ; current != end && *current >= '0'  &&  *current <= '9'; ++current )
						index = index * 10 + Value::UInt(*current - '0');
					args_.push_back( index );
				}
				if ( current == end  ||  *current++ != ']' )
					invalidPath( path, int(current - path.c_str()) );
			}
			else if ( *current == '%' )
			{
				addPathInArg( path, in, itInArg, PathArgument::kindKey );
				++current;
			}
			else if ( *current == '.' )
			{
				++current;
			}
			else
			{
				const char *beginName = current;
				while ( current != end  &&  !strchr( "[.", *current ) )
					++current;
				args_.push_back( std::string( beginName, current ) );
			}
		}
	}


	void 
		Path::addPathInArg( const std::string &path, 
		const InArgs &in, 
		InArgs::const_iterator &itInArg, 
		PathArgument::Kind kind )
	{
		if ( itInArg == in.end() )
		{
			// Error: missing argument %d
		}
		else if ( (*itInArg)->kind_ != kind )
		{
			// Error: bad argument type
		}
		else
		{
			args_.push_back( **itInArg );
		}
	}


	void 
		Path::invalidPath( const std::string &path, 
		int location )
	{
		// Error: invalid path.
	}


	const Value &
		Path::resolve( const Value &root ) const
	{
		const Value *node = &root;
		for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
		{
			const PathArgument &arg = *it;
			if ( arg.kind_ == PathArgument::kindIndex )
			{
				if ( !node->isArray()  ||  node->isValidIndex( arg.index_ ) )
				{
					// Error: unable to resolve path (array value expected at position...
				}
				node = &((*node)[arg.index_]);
			}
			else if ( arg.kind_ == PathArgument::kindKey )
			{
				if ( !node->isObject() )
				{
					// Error: unable to resolve path (object value expected at position...)
				}
				node = &((*node)[arg.key_]);
				if ( node == &Value::null )
				{
					// Error: unable to resolve path (object has no member named '' at position...)
				}
			}
		}
		return *node;
	}


	Value 
		Path::resolve( const Value &root, 
		const Value &defaultValue ) const
	{
		const Value *node = &root;
		for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
		{
			const PathArgument &arg = *it;
			if ( arg.kind_ == PathArgument::kindIndex )
			{
				if ( !node->isArray()  ||  node->isValidIndex( arg.index_ ) )
					return defaultValue;
				node = &((*node)[arg.index_]);
			}
			else if ( arg.kind_ == PathArgument::kindKey )
			{
				if ( !node->isObject() )
					return defaultValue;
				node = &((*node)[arg.key_]);
				if ( node == &Value::null )
					return defaultValue;
			}
		}
		return *node;
	}


	Value &
		Path::make( Value &root ) const
	{
		Value *node = &root;
		for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
		{
			const PathArgument &arg = *it;
			if ( arg.kind_ == PathArgument::kindIndex )
			{
				if ( !node->isArray() )
				{
					// Error: node is not an array at position ...
				}
				node = &((*node)[arg.index_]);
			}
			else if ( arg.kind_ == PathArgument::kindKey )
			{
				if ( !node->isObject() )
				{
					// Error: node is not an object at position...
				}
				node = &((*node)[arg.key_]);
			}
		}
		return *node;
	}


} // namespace Json
